/*
 * SPDX-License-Identifier: Apache-2.0
 */

import { Context, Contract, Info, Returns, Transaction } from 'fabric-contract-api';
import { on } from 'process';
import { Copyright } from './my-asset';
const SHA256 = require("crypto-js/sha256");

@Info({title: 'MyAssetContract', description: 'My Smart Contract' })
export class MyAssetContract extends Contract {

    @Transaction(false)
    @Returns('boolean')
    public async copyrightExists(ctx: Context, copyright_id: string): Promise<boolean> {
        const data: Uint8Array = await ctx.stub.getState(copyright_id);
        return (!!data && data.length > 0);
    }

    @Transaction()
    @Returns('copyright_id')
    public async copyrightRegistration(ctx: Context, title: string, description: string, 
        create_date: string, creator:string, password: string): Promise<string> {
        const newRegistration: Copyright = new Copyright();
        newRegistration.m_title = title;
        newRegistration.m_description = description;
        newRegistration.m_create_date = create_date;
        newRegistration.m_creator = creator;
        newRegistration.m_possessor = creator;
        newRegistration.m_is_shared = false;
        newRegistration.m_varifacation_code = SHA256(creator + password).toString();
        
        const copyright_id: string = SHA256(newRegistration.m_title + newRegistration.m_description).toString();
        const exists: boolean = await this.copyrightExists(ctx, copyright_id);
        if (exists) {
            throw new Error(`Copyright ${copyright_id} already exists`);
        }
        
        const buffer: Buffer = Buffer.from(JSON.stringify(newRegistration));
        await ctx.stub.putState(copyright_id, buffer);
        return copyright_id;
    }

    @Transaction(false)
    @Returns('myCopyright')
    public async readRegistration(ctx: Context, copyright_id: string): Promise<Copyright> {
        const exists: boolean = await this.copyrightExists(ctx, copyright_id);
        if (!exists) {
            throw new Error(`The copyright ${copyright_id} does not exist`);
        }
        const data: Uint8Array = await ctx.stub.getState(copyright_id);
        const myCopyright: Copyright = JSON.parse(data.toString()) as Copyright;
        return myCopyright;
    }

    @Transaction()
    public async openMyCopyright(ctx: Context, copyright_id: string): Promise<void> {
        const exists: boolean = await this.copyrightExists(ctx, copyright_id);
        if (!exists) {
            throw new Error(`The copyright ${copyright_id} does not exist`);
        }
        const data: Uint8Array = await ctx.stub.getState(copyright_id);
        const temp_str = String.fromCharCode.apply(null,data);
        const myAsset: Copyright = JSON.parse(temp_str);

        myAsset.m_is_shared = true;
        const buffer: Buffer = Buffer.from(JSON.stringify(myAsset));
        await ctx.stub.putState(copyright_id, buffer);
    }

    @Transaction()
    public async deleteMyCopyright(ctx: Context, copyright_id: string): Promise<void> {
        const exists: boolean = await this.copyrightExists(ctx, copyright_id);
        if (!exists) {
            throw new Error(`The copyright ${copyright_id} does not exist`);
        }
        await ctx.stub.deleteState(copyright_id);
    }

    @Transaction()
    public async copyrightTransfer(ctx: Context, copyright_id: string, old_pwd: string, assignee: string, new_pwd: string): Promise<boolean>{
        const exists: boolean = await this.copyrightExists(ctx, copyright_id);
        if (!exists) {
            throw new Error(`The copyright ${copyright_id} does not exist`);
        }
        const data: Uint8Array = await ctx.stub.getState(copyright_id);
        const targetCopyright: Copyright = await JSON.parse(data.toString()) as Copyright;
        if(targetCopyright.m_varifacation_code != SHA256(targetCopyright.m_creator+old_pwd).toString()){
            throw new Error(`Possesser varification failed`);
        }

        targetCopyright.m_varifacation_code = SHA256(assignee + new_pwd).toString();
        targetCopyright.m_possessor = assignee;
        const buffer = Buffer.from(JSON.stringify(targetCopyright));
        await ctx.stub.putState(copyright_id, buffer);
        return true;
    }

    @Transaction(false)
    public async queryAllCopyrightByPossessorID(ctx: Context,possesser: string): Promise<string> {
        const startKey = '';
        const endKey = '';
        const iterator = await ctx.stub.getStateByRange(startKey, endKey);
        const allResults = [];
        while (true) {
            const res = await iterator.next();
            if (res.value && res.value.value.toString()) {
                console.log(res.value.value.toString());
                const Key = res.value.key;
                let Record;
                try {
                    Record = JSON.parse(res.value.value.toString());
                } catch (err) {
                    console.log(err);
                    Record = res.value.value.toString();
                }
                if(Record.m_possessor == possesser){
                    allResults.push({ Key, Record });
                }  
            }
            if (res.done) {
                console.log('end of data');
                await iterator.close();
                console.info(allResults);
                return JSON.stringify(allResults);
            }
        }
    }
}
